﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace WingsOverSpace
{
    class Player : WingsDrawableGameComponent 
    {
        Vector2 Velocity { get; set; }
        Texture2D explosion;
        Texture2D fullhealthbar;
        Texture2D fourhealth;
        Texture2D threehealth;
        Texture2D twohealth;
        Texture2D onehealth;
        Texture2D nohealth;
        SpriteBatch spriteBatch;
        float LastShot = 0f;
        public float unpausedAtTime = 0f;
        int Score = 0;
        SpriteFont ScoreFont;
        SpriteFont LivesFont;
        SpriteFont Healthfont;
        public int Lives = 3;
        private int Health = 5;

        public Player(Game g, Vector2 position)
            : base(g)
        {
            Position = position;
            Velocity = new Vector2(0, 0);
            SpriteHeightDivFactor = 1;
            SpriteWidthDivFactor = 1;
            SpriteScaleFactor = 0.65f;
        }

        public void reinit(Vector2 position)
        {
            Position = position;
            Velocity = new Vector2(0,0);
            Score = 0;
            Lives = 3;
            Health = 5;
        }

        protected override void LoadContent()
        {
            //sprite = Game.Content.Load<Texture2D>("BlueShip");
            sprite = Game.Content.Load<Texture2D>("playership");
            explosion = Game.Content.Load<Texture2D>("BlueShipExplosion0");
            fullhealthbar = Game.Content.Load<Texture2D>("fullhealth");
            fourhealth = Game.Content.Load<Texture2D>("fourhealth");
            threehealth = Game.Content.Load<Texture2D>("threehealth");
            twohealth = Game.Content.Load<Texture2D>("twohealth");
            onehealth = Game.Content.Load<Texture2D>("onehealth");
            nohealth = Game.Content.Load<Texture2D>("nohealth");

            spriteBatch = new SpriteBatch(Game.GraphicsDevice);
            float screenscale = (float)GraphicsDevice.Viewport.Width / 1024f; //Matrix used to scale sprites by viewport size
            SpriteScale = Matrix.CreateScale(screenscale, screenscale, 1);
            ScoreFont = Game.Content.Load<SpriteFont>("ScoreFont");
            LivesFont = Game.Content.Load<SpriteFont>("LivesFont");
            Healthfont = Game.Content.Load<SpriteFont>("Healthfont");

            base.LoadContent();
        }

        public override void Draw(GameTime gameTime)
        {
            // Basically, this is a bunch of rectangles containing the parts of the sprite that we want to draw, because the sprites are in spritesheets so the animations will be implemented by changing rectangles.
            // Currently, I only have the program draw the fullHealth ship, but once we implement the health system we'll have to switch between rectangles, and when the player dies we'll also have to use the explosion
            // rectangles for that animation.

            Vector2 offset = new Vector2(sprite.Width / (2 * SpriteWidthDivFactor), sprite.Height / (2 * SpriteHeightDivFactor));
            Vector2 offset2 = new Vector2(explosion.Width / 6, explosion.Height / 2);
            Rectangle fullHealth = new Rectangle(0, 0, sprite.Width / SpriteWidthDivFactor, sprite.Height / SpriteHeightDivFactor);
            Rectangle oneDamage = new Rectangle(100, 0, sprite.Width / SpriteWidthDivFactor, sprite.Height / SpriteHeightDivFactor);
            Rectangle twoDamage = new Rectangle(200, 0, sprite.Width / SpriteWidthDivFactor, sprite.Height / SpriteHeightDivFactor);
            Rectangle threeDamage = new Rectangle(300, 0, sprite.Width / SpriteWidthDivFactor, sprite.Height / SpriteHeightDivFactor);
            Rectangle fourDamage = new Rectangle(400, 0, sprite.Width / SpriteWidthDivFactor, sprite.Height / SpriteHeightDivFactor);
            Rectangle fiveDamage = new Rectangle(500, 0, sprite.Width / SpriteWidthDivFactor, sprite.Height / SpriteHeightDivFactor);
            Rectangle startExplosion = new Rectangle(0, 0, explosion.Width, explosion.Height / 3);
            Rectangle explosionContinues = new Rectangle(0, 500, explosion.Width, explosion.Height / 3);
            Rectangle endExplosion = new Rectangle(0, 1000, explosion.Width, explosion.Height / 3);
            
            spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, 
                null, null, null, SpriteScale);

            spriteBatch.DrawString(ScoreFont, "Score: " + Score, new Vector2(15, 15),
                Color.White);
            spriteBatch.DrawString(LivesFont, "Lives:", new Vector2(15, 730), Color.White);
            spriteBatch.DrawString(Healthfont, "HEALTH", new Vector2(800, 730), Color.Red);
            for (int i = 0; i < Lives; i++)
            {
                spriteBatch.Draw(sprite, new Vector2(70 + 30 * i, 730), fullHealth,
                    Color.White, 0f, new Vector2(0, 0), 0.30f, SpriteEffects.None, 0);
            }
            spriteBatch.End();

            switch (ExplodeOrder)
            {
                case ExplosionOrder.NoExplosion:
                    spriteBatch.Begin();
                    if (Health == 5)
                    {
                        spriteBatch.Draw(fullhealthbar, new Vector2(881, 731), null, Color.White, 0f, new Vector2(0, 0), SpriteScaleFactor, SpriteEffects.None, 0f);
                        //spriteBatch.Draw(sprite, Position - offset, fullHealth, Color.White, 0f, new Vector2(0, 0), SpriteScaleFactor, SpriteEffects.None, 0);
                   }
                    else if (Health == 4)
                    {
                        spriteBatch.Draw(fourhealth, new Vector2(881, 731), null, Color.White, 0f, new Vector2(0, 0), SpriteScaleFactor, SpriteEffects.None, 0f);
                        /*
                        //spriteBatch.Draw(sprite, Position - offset, oneDamage, Color.White, 0f, new Vector2(0, 0), SpriteScaleFactor, SpriteEffects.None, 0.05f);
                        spriteBatch.Draw(sprite, boundBox, null, Color.White,
                            0f, new Vector2(0, 0), SpriteEffects.None, 0);
                        */
                    }
                    else if (Health == 3)
                    {
                        spriteBatch.Draw(threehealth, new Vector2(881, 731), null, Color.White, 0f, new Vector2(0, 0), SpriteScaleFactor, SpriteEffects.None, 0f);
                        /*
                        //spriteBatch.Draw(sprite, Position - offset, twoDamage, Color.White, 0f, new Vector2(0, 0), SpriteScaleFactor, SpriteEffects.None, 0.05f);
                        spriteBatch.Draw(sprite, boundBox, null, Color.White,
                            0f, new Vector2(0, 0), SpriteEffects.None, 0);
                        */
                    }
                    else if (Health == 2)
                    {
                        spriteBatch.Draw(twohealth, new Vector2(881, 731), null, Color.White, 0f, new Vector2(0, 0), SpriteScaleFactor, SpriteEffects.None, 0f);
                        /*
                        //spriteBatch.Draw(sprite, Position - offset, threeDamage, Color.White, 0f, new Vector2(0, 0), SpriteScaleFactor, SpriteEffects.None, 0.05f);
                        spriteBatch.Draw(sprite, boundBox, null, Color.White,
                            0f, new Vector2(0, 0), SpriteEffects.None, 0);
                        */
                    }
                    else if (Health == 1)
                    {
                        spriteBatch.Draw(onehealth, new Vector2(881, 731), null, Color.White, 0f, new Vector2(0, 0), SpriteScaleFactor, SpriteEffects.None, 0f);
                        //spriteBatch.Draw(sprite, Position - offset, fourDamage, Color.White, 0f, new Vector2(0, 0), SpriteScaleFactor, SpriteEffects.None, 0.05f);
                        /*
                        spriteBatch.Draw(sprite, boundBox, null, Color.White,
                            0f, new Vector2(0, 0), SpriteEffects.None, 0);
                        */
                    }
                    else if (Health == 0)
                    {
                        spriteBatch.Draw(nohealth, new Vector2(881, 731), null, Color.White, 0f, new Vector2(0, 0), SpriteScaleFactor, SpriteEffects.None, 0f);
                        /*
                        //spriteBatch.Draw(sprite, Position - offset, fiveDamage, Color.White, 0f, new Vector2(0, 0), SpriteScaleFactor, SpriteEffects.None, 0.05f);
                        spriteBatch.Draw(sprite, boundBox, null, Color.White,
                            0f, new Vector2(0, 0), SpriteEffects.None, 0);
                        */

                    }
                    spriteBatch.Draw(sprite, boundBox, null, Color.White,
                         0f, new Vector2(offset.X, offset.Y), SpriteEffects.None, 0);
                    spriteBatch.End();
                    break;
                default:
                    spriteBatch.Begin();
                    spriteBatch.Draw(explosion, Position - offset2, startExplosion, Color.White, 0f, new Vector2(0, 0), 0.15f, SpriteEffects.None, 0.05f);
                    spriteBatch.End();
                    break;

            }
        }

        public override void Update(GameTime gameTime)
        {
            boundBox = new Rectangle((int)(Position.X - SpriteScaleFactor * sprite.Width / (2 * SpriteWidthDivFactor)),
                (int)(Position.Y - SpriteScaleFactor * sprite.Height / (2 * SpriteHeightDivFactor)),
                (int)(SpriteScaleFactor * sprite.Width / SpriteWidthDivFactor),
                (int)(SpriteScaleFactor * sprite.Height / SpriteHeightDivFactor));

            KeyboardState k = Keyboard.GetState();
            checkForCollision();
            float elapsedSeconds = (float)gameTime.ElapsedGameTime.TotalSeconds;
            float totalSeconds = (float)gameTime.TotalGameTime.TotalSeconds;

            int MaxX = GraphicsDevice.Viewport.Width - sprite.Width / 24; 
            int MinX = sprite.Width / 12 + 45;
            int MaxY = GraphicsDevice.Viewport.Height - sprite.Height / 12; //These Y numbers work with this sprite because it's not perfectly cropped
            int MinY = sprite.Height / 2; //divide sprite height to get single ship size

            Velocity = new Vector2(0, 0); //clear out old velocity
            
            if (k.IsKeyDown(Keys.Left) && Position.X > MinX)
            {
                Velocity += new Vector2(-400, 0);
            }

            if (k.IsKeyDown(Keys.Right) && Position.X < MaxX)
            {
                Velocity += new Vector2(400, 0);
            }

            if (k.IsKeyDown(Keys.Up) && Position.Y > MinY)
            {
                Velocity += new Vector2(0, -400); // up and down reversed because windows uses (0,0) as top left corner
            }

            if (k.IsKeyDown(Keys.Down) && Position.Y < MaxY)
            {
                Velocity += new Vector2(0, 400);
            }

            if (k.IsKeyDown(Keys.Escape))
            {
                Game.Exit();
            }

            foreach (WingsDrawableGameComponent comp in base.Game.Components)
            {
                if ((comp is GravitationalAsteroid) && (comp.Visible == true))
                {
                    
                    Vector2 gravityVector = comp.Position - Position;
                    if ((gravityVector.Length() < 300f) && (Position.X > MinX) && (Position.X < MaxX)
                        && (Position.Y > MinY) && (Position.Y < MaxY))
                    {
                        gravityVector.Normalize();
                        Velocity += (comp as GravitationalAsteroid).gravity * elapsedSeconds * gravityVector;
                    }
                }
            }

            Position += Velocity * elapsedSeconds;

            if ((totalSeconds - LastShot > 0.3) && (totalSeconds - unpausedAtTime > .2))
            {
                if (k.IsKeyDown(Keys.Space)) {
                    LastShot = totalSeconds;

                    WingsDrawableGameComponent comp = UnusedObject(ComponentType.PlayerShot);
                    if (comp != null)
                    {
                        (comp as PlayerShot).Visible = true;
                        (comp as PlayerShot).Position = new Vector2 (Position.X, this.boundBox.Top);
                    }
                    else
                    {
                        //throw some kind of error
                    }
                    
                }
            }

            if (Health == 0)
            {
                LoseLife();
                if (Lives >= 0)
                    FullHealth();

            }

            base.Update(gameTime);
        }

        public void AddScore(int amount)
        {
            Score += amount;
        }

        public void GainLife()
        {
            Lives++;
        }

        public void LoseLife()
        {
            //ExplodeOrder++;
            Lives--;
            if (Lives > 0)
            {
                FullHealth();
                Position = new Vector2(500, 750);
            }
        }

        public void TakeDamage()
        {
            Health--;
            if (Health < 1)
            {
                LoseLife();
            }
        }

        public void GetHealth()
        {
            Health++;
        }

        public void FullHealth()
        {
            Health = 5;

        }


        public void checkForCollision()
        {
            foreach( WingsDrawableGameComponent comp in base.Game.Components)
            {
                if ((this != comp) && (comp.Visible == true))
                {
                    if (comp is EnemyShot) //checks if player gets shot and removes health if so.
                    {
                        if (boundBox.Intersects(comp.boundBox))
                        {
                            this.TakeDamage();
                            comp.toBeDeleted = true;
                        }
                    }
                    else if (comp is lifeUp)
                    {
                        if (boundBox.Intersects(comp.boundBox))
                        {
                            GainLife();
                            comp.toBeDeleted = true;
                        }
                    }
                    else if (comp is moneyPowerUp)
                    {
                        if (boundBox.Intersects(comp.boundBox))
                        {
                            AddScore(1000);
                            comp.toBeDeleted = true;
                        }
                    }
                    else if (comp is Asteroid)
                    {
                        if (boundBox.Intersects(comp.boundBox))
                        {
                            this.LoseLife();
                            comp.toBeDeleted = true;
                        }
                    }
                    else if (comp is PlayerShot)
                    {
                    }
                    else // must be an enemy at this point, will need to change when other things are implemented
                    {
                        if (boundBox.Intersects(comp.boundBox))
                        {
                            this.LoseLife();
                            comp.ExplodeOrder++;
                            //comp.Position = new Vector2(0, 0);
                        }

                    }
                }
            }
        }

    }

    class PlayerShot : WingsDrawableGameComponent
    {
        public Vector2 Velocity { get; set; }
        SpriteBatch spriteBatch;

        public PlayerShot(Game g, Vector2 position)
            : base(g)
        {
            Position = position;
            Velocity = new Vector2(0, -1000f);
            SpriteScaleFactor = 0.5f;
            Visible = false;
        }

        public override void Draw(GameTime gameTime)
        {
            base.Draw(gameTime);
            Vector2 offset = new Vector2(sprite.Width / 2, sprite.Height / 2);
            spriteBatch.Begin();
            spriteBatch.Draw(sprite, Position - offset, null, Color.White,
                0f, new Vector2(0, 0), SpriteScaleFactor, SpriteEffects.None, 0);
            spriteBatch.End();
        }

        protected override void LoadContent()
        {
            sprite = Game.Content.Load<Texture2D>("possibleLaser");
            spriteBatch = new SpriteBatch(Game.GraphicsDevice);
            base.LoadContent();
        } 

        public override void Update(GameTime gameTime)
        {
            boundBox = new Rectangle((int)(Position.X - SpriteScaleFactor * sprite.Width / (2 * SpriteWidthDivFactor)),
                (int)(Position.Y - SpriteScaleFactor * sprite.Height / (2 * SpriteHeightDivFactor)),
                (int)(SpriteScaleFactor * sprite.Width / SpriteWidthDivFactor),
                (int)(SpriteScaleFactor * sprite.Height / SpriteHeightDivFactor));

            if (Position.Y < -100) toBeDeleted = true;

            if (toBeDeleted == true)
            {
                Visible = false;
                toBeDeleted = false;
            }

            float elapsedSeconds = (float)gameTime.ElapsedGameTime.TotalSeconds;
            checkForCollision();
            Position += Velocity * elapsedSeconds;

            base.Update(gameTime);
            
        }

        public void checkForCollision()
        {
            foreach (WingsDrawableGameComponent comp in base.Game.Components)
            {
                if ((this != comp) && (comp.Visible == true))
                {
                    
                    if (!((comp is Player) || (comp is PlayerShot))) //Look for everything that is not a player or a laser
                    {
                        if (boundBox.Intersects(comp.boundBox))
                        {
                            if (comp as Enemy != null)
                            {
                                comp.ExplodeOrder++;
                                this.toBeDeleted = true;
                                (Game.Components[0] as Player).AddScore(50);
                                Position = new Vector2(0, 0);
                            }
                            if (comp as Asteroid != null)
                            {
                                comp.toBeDeleted = true;
                                this.toBeDeleted = true;
                                (Game.Components[0] as Player).AddScore(50);
                                Position = new Vector2(0, 0);
                            }
                        }
                    }

                }
            }
        }
    }
}

